package ldh.im.fxgui.component.cell;

import com.google.common.eventbus.Subscribe;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXTextField;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.TextFlow;
import ldh.im.dto.business.base.DataChangeReq;
import ldh.im.dto.enums.DataSubType;
import ldh.im.dto.enums.DataType;
import ldh.im.fxbase.dao.ImGroupDao;
import ldh.im.fxbase.dao.ImSessionDao;
import ldh.im.fxbase.data.event.EventBusFactory;
import ldh.im.fxbase.data.event.GroupNameChange;
import ldh.im.fxbase.data.event.SessionChange;
import ldh.im.fxbase.data.pojo.*;
import ldh.im.fxbase.data.pojo.status.ImSessionType;
import ldh.im.fxbase.richtext.ImTextField;
import ldh.im.fxbase.richtext.TextItem;
import ldh.im.fxbase.rpc.service.RpcMessageService;
import ldh.im.fxbase.service.ImSessionService;
import ldh.im.fxbase.util.*;
import ldh.im.fxgui.component.ImStage;
import ldh.im.fxgui.controller.MessageSendController;
import ldh.im.fxgui.controller.MessageSessionController;
import ldh.im.fxbase.util.ImCacheFactory;
import ldh.im.fxgui.util.UiUtil;
import ldh.im.fxgui.util.UserHeadImageUtil;
import ldh.im.util.DateUtil;
import org.kordamp.ikonli.javafx.FontIcon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * 会话ListCell
 */
public class SessionView extends AnchorPane {

    private static final Logger LOGGER = LoggerFactory.getLogger(SessionView.class);

    private ImSession imSession;

    private ImageView messageImageView;
    private Pane groupImageView;
    private Label nameLabel;
    private TextFlow lastedMessageTextFlow;
    private Label createDateLabel;
    private Label hotMessageTotalLabel;
    private Pane hotMessagePane;
    private StackPane headIconPane = new StackPane();

    private FontIcon closeIcon;
    private IntegerProperty hotMessageNumProperty = new SimpleIntegerProperty(0);
    private StringProperty lastedMessageProperty = new SimpleStringProperty("");

    private MessageSessionController messageSessionController;
    private Pane popupPane = null;

    public SessionView(ImSession imSession, MessageSessionController messageSessionController) {
        this.imSession = imSession;
        this.messageSessionController = messageSessionController;
        ImHotMessageSingleton.getInstance().bindHotMessage(imSession.getId(), hotMessageNumProperty);
        ImHotMessageSingleton.getInstance().bindLastedMessage(imSession.getId(), lastedMessageProperty);

        this.getStyleClass().add("session-view");
        initUi();

        initEvent();

        setData(imSession);
    }

    public void dispose() {
        ImHotMessageSingleton.getInstance().unBindHotMessage(imSession.getId(), hotMessageNumProperty);
        ImHotMessageSingleton.getInstance().unBindLastedMessage(imSession.getId(), lastedMessageProperty);
        EventBusFactory.getInstance().unregister(this);
    }

    @Subscribe
    public void groupNameChange(GroupNameChange groupNameChange) {
        if (!groupNameChange.getGroupId().equals(imSession.getGroupCode())) return;
        FxThreadUtil.runLater(()->{
            nameLabel.setText(groupNameChange.getName());
        });
    }

    @Subscribe
    public void sessionChange(SessionChange sessionChange) {
        try {
            if (!sessionChange.getSessionId().equals(imSession.getId())) return;
            ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);
            ImGroupDao imGroupDao = BeanFactory.getInstance().getBean(ImGroupDao.class);

            ImSession session = imSessionDao.getSessionById(imSession.getId());
            ImGroup group = imGroupDao.getByUserIdAndId(session.getCurrentUserId(), session.getGroupCode());
            imSession.setImGroup(group);
//            imSession = session;
            FxThreadUtil.runLater(()->{
                setData(session);
            });
        } catch (Exception e) {
            LOGGER.error("加载会话失败", e);
        }
    }

    public void setHotTotal(int total) {
        if (total>0) {
//            int total = value >= 99 ? 99 : total;
            hotMessageTotalLabel.setText(total + "");
            hotMessagePane.setVisible(true);
        } else {
            hotMessagePane.setVisible(false);
        }
    }

    private void initUi() {
        GridPane gridPane = buildMessageSessionUi();

        closeIcon = IconUtil.createIcon("fa-close", 18, Color.WHITE);
        closeIcon.setVisible(false);
        AnchorPane.setRightAnchor(closeIcon, 18d);
        AnchorPane.setTopAnchor(closeIcon, 22d);
        closeIcon.setOnMouseClicked(e->{
            removeItem(e);
            e.consume();  // 防止事件传递到SessionView中，触发了：SellectNode事件
        });

        this.getChildren().addAll(gridPane, closeIcon);
    }

    private void initEvent() {
        hotMessagePane.visibleProperty().bind(hotMessageNumProperty.greaterThan(0));
        hotMessageTotalLabel.textProperty().bind(hotMessageNumProperty.asString());
        hotMessageTotalLabel.visibleProperty().bind(hotMessageNumProperty.greaterThan(0));

        lastedMessageProperty.addListener(l-> changeLastedMessage(lastedMessageProperty.get()));

        this.setOnMouseEntered(e->{
            closeIcon.setVisible(true);
        });
        this.setOnMouseExited(e->{
            closeIcon.setVisible(false);
        });

        this.setOnMousePressed(e->{
            if (e.getButton() != MouseButton.SECONDARY) return;
            popupPane = buildPopPane();
            UiUtil.getMainPopup().getContent().clear();
            UiUtil.getMainPopup().getContent().add(popupPane);
            UiUtil.getMainPopup().show(this.getScene().getWindow(), e.getScreenX(), e.getScreenY());
        });

//        hotMessagePane.setVisible(false);

    }

    public void setData(ImSession imSession) {
        String userId = UiUtil.getLoginImUser().getUserId();
        if (imSession.getSessionType() == ImSessionType.chat) {
            if (imSession.isP2p()) {
                ImUser imUser = ImCacheFactory.getInstance().getUser(imSession.getToUserId());
                nameLabel.setText(imUser.getUserName());
            } else {
                ImGroup imGroup = ImCacheFactory.getInstance().getImGroup(imSession.getCurrentUserId(), imSession.getGroupCode());
                nameLabel.setText(imGroup.getName());
            }
        } else {
            nameLabel.setText(imSession.getName());
        }

        nameLabel.setMaxWidth(150);
        createDateLabel.setText(DateUtil.format(imSession.getUpdateTime(), "HH:mm"));

        headIconPane.getChildren().clear();

        // 超过三小时不展示最新消息
        if (DateUtil.hasExceededTime(imSession.getUpdateTime(), 60 * 24 * 3)) {
            String latelyMessage = imSession.getLatelyMessage();
            changeLastedMessage(latelyMessage);
        }

        if (imSession.isP2p()) {
            messageImageView = (ImageView) UserHeadImageUtil.createSessionImage(imSession);
            messageImageView.setFitWidth(36d);
            messageImageView.setFitHeight(36d);
            Circle circle = new Circle(18, 18, 18);
            messageImageView.setClip(circle);

            headIconPane.setAlignment(messageImageView, Pos.CENTER);
            headIconPane.getChildren().add(messageImageView);

        } else {
            groupImageView = (Pane) UserHeadImageUtil.createSessionImage(imSession);
            groupImageView.setPrefSize(36, 36);
            groupImageView.setMinSize(36, 36);
            headIconPane.getChildren().add(groupImageView);
//            groupImageView.setAlignment(Pos.CENTER);
        }

        if (imSession != null) {
            if (imSession.isDisturb(userId)) {
                FontIcon redCircle = IconUtil.createIcon("fa-circle", 12, Color.RED);
                hotMessagePane.getChildren().add(0, redCircle);
                hotMessagePane.getChildren().remove(1);
            }
        }
    }

    private void changeLastedMessage(String latelyMessage) {
        latelyMessage = StringUtil.getLatelyMessage(latelyMessage);
        if (latelyMessage != null) {
            if (latelyMessage.contains(TextItem.SPLIT_STRING)) {
                lastedMessageTextFlow.getChildren().setAll(new ImTextField(latelyMessage));
            } else {
                lastedMessageTextFlow.getChildren().setAll(new Label(latelyMessage));
            }
        }
    }

    private GridPane buildMessageSessionUi() {
        GridPane gridPane = new GridPane();
        gridPane.setGridLinesVisible(false);
        gridPane.setHgap(5);
        gridPane.setVgap(5);
        AnchorPane.setTopAnchor(gridPane, 0d);
        AnchorPane.setRightAnchor(gridPane, 0d);
        AnchorPane.setLeftAnchor(gridPane, 0d);
        AnchorPane.setBottomAnchor(gridPane, 0d);

        StackPane headIconContainer = new StackPane();
        gridPane.add(headIconContainer, 0, 0, 1, 2);

        headIconPane.getStyleClass().add("head-icon-pane");

        // 未读消息
        hotMessagePane = new StackPane();
        hotMessagePane.getStyleClass().add("hot-pane");
        StackPane.setAlignment(hotMessagePane, Pos.TOP_RIGHT);
        FontIcon redCircle = IconUtil.createIcon("fa-circle", 18, Color.RED);
        hotMessageTotalLabel = new Label();
        hotMessageTotalLabel.getStyleClass().add("hot-label");
        hotMessagePane.getChildren().addAll(redCircle,  hotMessageTotalLabel);

        headIconContainer.getChildren().addAll(headIconPane, hotMessagePane);

        nameLabel = new Label();
        nameLabel.getStyleClass().add("session-name");
        gridPane.add(nameLabel, 1, 0);

        lastedMessageTextFlow = new TextFlow();
        lastedMessageTextFlow.getStyleClass().add("session-flow");
        gridPane.add(lastedMessageTextFlow, 1, 1);

        createDateLabel = new Label();
        createDateLabel.getStyleClass().add("session-day");
        gridPane.add(createDateLabel, 2, 0);

        Label tipLabel = new Label();
        tipLabel.getStyleClass().add("session-tip");
        gridPane.add(tipLabel, 2, 1);

        ColumnConstraints columnConstraints1 = new ColumnConstraints();
        columnConstraints1.setPrefWidth(36d);
        ColumnConstraints columnConstraints2 = new ColumnConstraints();
        columnConstraints2.setHgrow(Priority.ALWAYS);
        ColumnConstraints columnConstraints3 = new ColumnConstraints();
        columnConstraints3.setPrefWidth(38d);
        columnConstraints3.setMinWidth(38d);
        gridPane.getColumnConstraints().addAll(columnConstraints1, columnConstraints2, columnConstraints3);

        RowConstraints rowConstraints1 = new RowConstraints();
        rowConstraints1.setPrefHeight(25d);
        RowConstraints rowConstraints2 = new RowConstraints();
        rowConstraints2.setPrefHeight(22d);
        gridPane.getRowConstraints().addAll(rowConstraints1, rowConstraints2);
        return gridPane;
    }

    private void removeItem(MouseEvent mouseEvent) {
        if (messageSessionController == null) return;
        messageSessionController.removeMessageSession(imSession);
//        imSession.setStatus(ImSessionStatus.disable);
        imSession.setUpdateTime(DateUtil.toDate(LocalDateTime.now().plusDays(-15)));
        ThreadPoolUtil.submit(()->{
            try {
                ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);
                imSessionDao.updateSession(imSession);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    private Pane buildPopPane() {
        VBox vBox = new VBox();
        vBox.getStyleClass().add("session-pop-pane");
        JFXButton b1 = createTopButton();                  // 置顶
        JFXButton b2 = createDisturbButton();              // 消息免打扰
        JFXButton b3 = createEditGroupNameButton();        // 修改群名称
        JFXButton b4 = createSingleWindowButton();         // 在独立窗口打开
        Separator separator = new Separator();
        JFXButton b5 = createHideSessionButton();          // 不显示聊天
        JFXButton b6 = createDeleteSessionButton();        // 删除聊天

        vBox.getChildren().addAll(b1, b2);
        if (imSession.getSessionType() == ImSessionType.chat && !imSession.isP2p()) { // 群可以修改群名称
            vBox.getChildren().add(b3);
        }
        vBox.getChildren().addAll(b4, separator, b5, b6);
        return vBox;
    }

    /************************************会议弹出框 start***************************************************************/
    private JFXButton createTopButton() {
        JFXButton button = new JFXButton("置顶");
        button.setUserData(true);
        String userId = UiUtil.getLoginImUser().getUserId();
        if (imSession.getGroupCode() != null) {
            ImGroupUser groupUser = imSession.getImGroup().getCurrentGroupUser();
            if (groupUser.getTop()) {
                button.setText("取消置顶");
                button.setUserData(false);
            }
        } else {
            boolean isSender = imSession.getFromUserId().compareTo(imSession.getToUserId())>=0;
            if (imSession.isTop() && isSender) {
                button.setText("取消置顶");
                button.setUserData(false);
            } else if (imSession.isTop2() && !isSender) {
                button.setText("取消置顶");
                button.setUserData(false);
            }
        }

        button.setOnAction(e->{
            UiUtil.getMainPopup().hide();

            ImSessionService imSessionService = BeanFactory.getInstance().getBean(ImSessionService.class);
            boolean isTop = (boolean) button.getUserData();
            Task task = imSessionService.topSession(userId, imSession, isTop);
            task.setOnSucceeded(s->{
                messageSessionController.reloadMessageSession(imSession);
            });
            UiUtil.getMainPopup().hide();
        });
        return button;
    }

    private JFXButton createDisturbButton() {
        JFXButton button = new JFXButton("消息免打扰");
        button.setUserData(true);
        String userId = UiUtil.getLoginImUser().getUserId();
        if (imSession.getGroupCode() != null) {
            ImGroupUser groupUser = imSession.getImGroup().getCurrentGroupUser();
            if (groupUser.getDisturb()) {
                button.setText("取消免打扰");
                button.setUserData(false);
            }
        } else {
            if (imSession.isDisturb() && imSession.getFromUserId().compareTo(imSession.getToUserId())>=0) {
                button.setText("取消免打扰");
                button.setUserData(false);
            } else if (imSession.isDisturb2() && imSession.getFromUserId().compareTo(imSession.getToUserId())<0) {
                button.setText("取消免打扰");
                button.setUserData(false);
            }
        }
        button.setOnAction(e->{
            UiUtil.getMainPopup().hide();

            ImSessionService imSessionService = BeanFactory.getInstance().getBean(ImSessionService.class);
            boolean isDisturb = (boolean) button.getUserData();
            Task task = imSessionService.disturbSession(userId, imSession, isDisturb);
            task.setOnSucceeded(s->{
                messageSessionController.reloadMessageSession(imSession);
            });
        });
        return button;
    }

    private JFXButton createEditGroupNameButton() {
        JFXButton button = new JFXButton("修改群名称");
        button.setOnAction(e->{
            JFXTextField textField = new JFXTextField();
            textField.setText(imSession.getName());
            Map<String, Consumer<JFXDialog>> buttonsMap = new HashMap<>();
            buttonsMap.put("保存", dialog-> saveNewGroupName(textField.getText()));
            buttonsMap.put("取消", dialog-> dialog.close());

            UiUtil.getMainPopup().hide();
            DialogUtil.show("修改群名称", textField, false, buttonsMap);
        });
        return button;
    }

    private JFXButton createSingleWindowButton() {
        JFXButton button = new JFXButton("在独立窗口打开");
        button.setOnAction(e->{
            UiUtil.getMainPopup().hide();

            messageSessionController.removeMessageSession(imSession);
            ImStage stage = new ImStage(600, 700);

            stage.getCurrentScene().getStylesheets().add(this.getClass().getResource("/css/message-dialog.css").toExternalForm());
            stage.getCurrentScene().getStylesheets().add(this.getClass().getResource("/css/message-send.css").toExternalForm());
            RegionUtil.FxmlBean<Node, MessageSendController> fxmlBean = RegionUtil.loadFxmlBean(this.getClass().getResource("/fxml/MessageSendPane.fxml"));

            fxmlBean.getController().setImSession(imSession);
//            fxmlBean.getController().setMessageSessionController(messageSessionController);
            MessageSendController selectMessageSendController = fxmlBean.getController();
            selectMessageSendController.requestFocus();

            stage.setContent(fxmlBean.getNode());
            stage.setOnCloseRequest(ee->{
                LOGGER.debug("newStage do close event！");
                messageSessionController.switchSession(imSession);
            });
            stage.show();
        });
        return button;
    }

    private JFXButton createHideSessionButton() {
        JFXButton button = new JFXButton("不显示聊天");
        button.setOnAction(e->{
            UiUtil.getMainPopup().hide();
            Label content = new Label("你确认需要不显示此聊天吗？");
            Map<String, Consumer<JFXDialog>> buttonsMap = new HashMap<>();
            buttonsMap.put("确认", dialog-> {
                Task task = new Task() {

                    @Override
                    protected Object call() throws Exception {
                        ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);

                        imSession.setUpdateTime(DateUtil.toDate(LocalDateTime.now().plusDays(-15)));
                        imSessionDao.updateSession(imSession);
                        return null;
                    }
                };
                ThreadPoolUtil.submitTask(task);
                task.setOnSucceeded(s->{
                    messageSessionController.removeMessageSession(imSession);
                    UiUtil.getMainPopup().hide();
                });
            });
            buttonsMap.put("取消", dialog-> dialog.close());

            UiUtil.getMainPopup().hide();
            DialogUtil.show("不显示聊天", content, false, buttonsMap);
        });
        return button;
    }

    private JFXButton createDeleteSessionButton() {
        JFXButton button = new JFXButton("删除聊天");
        button.setOnAction(e->{
            UiUtil.getMainPopup().hide();
            Label content = new Label("您确认需要删除聊天记录吗？（删除不可恢复）");
            Map<String, Consumer<JFXDialog>> buttonsMap = new HashMap<>();
            buttonsMap.put("删除", dialog-> {
                Task task = new Task() {

                    @Override
                    protected Object call() throws Exception {
                        ImSessionService sessionService = new ImSessionService();
                        sessionService.delete(imSession.getId());
                        return null;
                    }
                };
                ThreadPoolUtil.submitTask(task);
                task.setOnSucceeded(s->{
                    messageSessionController.removeMessageSession(imSession);
                    UiUtil.getMainPopup().hide();
                });
            });
            buttonsMap.put("取消", dialog-> dialog.close());

            UiUtil.getMainPopup().hide();
            DialogUtil.show("删除聊天", content, false, buttonsMap);
        });
        return button;
    }

    /************************************会议弹出框 end***************************************************************/

    private void saveNewGroupName(String newGroupName) {
        if (newGroupName.trim().equals("")) return;
        if (imSession.isP2p()) return;
        imSession.setName(newGroupName);
        imSession.setUpdateTime(new Date());
        ImGroup imGroup = imSession.getImGroup();
        imGroup.setName(newGroupName);
        imGroup.setUpdateTime(new Date());
        nameLabel.setText(newGroupName);

        Task task = new Task() {

            @Override
            protected Object call() throws Exception {
                RpcMessageService rpcMessageService = RpcUtil.getRpcBootstrap().getRpcConfig().getClientBean(RpcMessageService.class);
                DataChangeReq dataChangeReq = new DataChangeReq();
                dataChangeReq.setType(DataType.group);
                dataChangeReq.setSubType(DataSubType.g_ed_name);
                dataChangeReq.setKey(imGroup.getCode());
                dataChangeReq.setValue(newGroupName);
                rpcMessageService.sendDataChange(dataChangeReq);

                ImSessionDao imSessionDao = BeanFactory.getInstance().getBean(ImSessionDao.class);
                ImGroupDao imGroupDao = BeanFactory.getInstance().getBean(ImGroupDao.class);
                imSessionDao.updateSession(imSession);
                imGroupDao.update(imGroup);

                GroupNameChange groupNameChange = new GroupNameChange(imGroup.getCode(), imGroup.getName());
                EventBusFactory.getInstance().post(groupNameChange);
                return null;
            }
        };
        ThreadPoolUtil.submitTask(task, "修改群");
        task.setOnSucceeded(e->{

        });
    }
}
